package drazing;

import java.io.*;
import javax.sound.sampled.*;

/**
 * Motor de Audio
 * @author xcubo
 */
public final class AudioEngine
{
    private static final int	EXTERNAL_BUFFER_SIZE = 128000;
    
    private AudioInputStream ais;
    private File sf;
    private String[] jukebox;
    private Clip music;
    private int track;

    public AudioEngine()
    {
        track = (int) Math.floor(Math.random()*7);

        jukebox = new String[7];
        jukebox[0] = "2nine.wav";
        jukebox[1] = "attra.wav";
        jukebox[2] = "death.wav";
        jukebox[3] = "drive.wav";
        jukebox[4] = "jar.wav";
        jukebox[5] = "plunk.wav";
        jukebox[6] = "xylo.wav"; 

        loadMusic(track);
    }

    /**
     * Carga la pista indicada
     * @param trk Indice de la pista
     */
    public void loadMusic(int trk)
    {
        String ruta = "resources/music/"+jukebox[trk];
        System.out.println("Pista: "+trk);
        System.out.println("cargando "+ ruta +" ... ");
        System.out.println(jukebox[trk]);

        try
        {
            String archivo = "audio.wav";
            System.out.println("Escribimos en el archivo " + archivo);

            sf = new File(archivo);
            InputStream is = this.getClass().getResourceAsStream(ruta);
            FileOutputStream archivoDestino = new FileOutputStream(sf);
            FileWriter fw = new FileWriter(sf);
            byte[] buffer = new byte[512*1024];
            int nbLectura;

            while ((nbLectura = is.read(buffer)) != -1)
            archivoDestino.write(buffer, 0, nbLectura);
        }
        catch (IOException ioe){}

        if (sf.exists())
            System.out.println("OK");
        else
            System.out.println("Fail");
    }

    /**
     * Reproduce la pista cargada
     */
    public void playMusic()
    {
        try
        {
            ais = AudioSystem.getAudioInputStream(sf);

            AudioFormat af = ais.getFormat();

            DataLine.Info info=new DataLine.Info(Clip.class,ais.getFormat(),
                            ((int) ais.getFrameLength()*af.getFrameSize()));
            music = (Clip)AudioSystem.getLine(info);
            music.open(ais);
            music.loop(Clip.LOOP_CONTINUOUSLY);                                 //numero de veces que se repite

        }
        catch(LineUnavailableException LUE){}
        catch(UnsupportedAudioFileException ee){}
        catch(IOException ea){}
    }
    /**
     * Detiene la reproduccion
     */
    public void stopMusic()
    {
        System.out.println("Deteniendo la musica...");
        music.stop();
        System.out.println("OK, limpiando el buffer...");
        music.flush();
        System.out.println("Musica parada");
    }

    /**
     * Metodo alternativo de reproduccion
     */
    public void playDataLine()
    {
        try
        {
                ais = AudioSystem.getAudioInputStream(sf);
        }
        catch (Exception e)
        {
                System.exit(1);
        }

        AudioFormat	af = ais.getFormat();
        SourceDataLine	line = null;
        DataLine.Info	info = new DataLine.Info(SourceDataLine.class, af);
        try
        {
                line = (SourceDataLine) AudioSystem.getLine(info);
                line.open(af);
        }
        catch (LineUnavailableException e)
        {
                System.exit(1);
        }
        catch (Exception e)
        {
                System.exit(1);
        }

        line.start();

        /*
          Ok, finally the line is prepared. Now comes the real
          job: we have to write data to the line. We do this
          in a loop. First, we read data from the
          AudioInputStream to a buffer. Then, we write from
          this buffer to the Line. This is done until the end
          of the file is reached, which is detected by a
          return value of -1 from the read method of the
          AudioInputStream.
        */
        int	nBytesRead = 0;
        byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];
        while (nBytesRead != -1)
        {
            try
            {
                nBytesRead = ais.read(abData, 0, abData.length);
            }
            catch (IOException e){}
            if (nBytesRead >= 0)
            {
                int	nBytesWritten = line.write(abData, 0, nBytesRead);
            }
        }

        /*
          Wait until all data are played.
          This is only necessary because of the bug noted below.
          (If we do not wait, we would interrupt the playback by
          prematurely closing the line and exiting the VM.)
        */
        //line.drain();
        //line.close();
    }
}
